#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

const int MAXN = 1000005;
vector<int> adj[MAXN];      // 邻接表存储树
vector<long long> values;    // 存储每个节点的吸光能力
vector<bool> used;          // 记录节点是否被使用
long long ans = 0;          // 存储最终答案

// DFS函数尝试所有可能的配对
void dfs(int n, long long curr_sum) {
    ans = max(ans, curr_sum);  // 更新答案

    // 尝试所有可能的配对
    for (int i = 1; i <= n; i++) {
        if (used[i]) continue;  // 如果i已被使用，跳过

        // 遍历i的所有相邻节点
        for (int j: adj[i]) {
            if (used[j]) continue;  // 如果j已被使用，跳过

            // 尝试配对i和j
            used[i] = used[j] = true;
            dfs(n, curr_sum + values[i] * values[j]);
            used[i] = used[j] = false;  // 回溯
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    cin >> n;

    // 初始化数组
    values.resize(n + 1);
    used.resize(n + 1, false);

    // 读入边
    for (int i = 0; i < n - 1; i++) {
        int a, b;
        cin >> a >> b;
        adj[a].push_back(b);
        adj[b].push_back(a);
    }

    // 读入吸光能力值
    for (int i = 1; i <= n; i++) {
        cin >> values[i];
    }

    // 开始DFS搜索所有可能的配对
    dfs(n, 0);

    cout << ans << endl;

    return 0;
}
